
package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.RolePermissionConverter;
import com.cskaoyan.wordmemorize.dao.entity.PermissionDO;
import com.cskaoyan.wordmemorize.dao.entity.RoleDO;
import com.cskaoyan.wordmemorize.dao.entity.RolePermissionDO;
import com.cskaoyan.wordmemorize.dao.mapper.PermissionMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RoleMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RolePermissionMapper;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.PermissionCommand;
import com.cskaoyan.wordmemorize.request.RoleCommand;
import com.cskaoyan.wordmemorize.request.RolePermissionCommand;
import com.cskaoyan.wordmemorize.service.RolePermissionService;
import org.apache.ibatis.executor.BatchResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RolePermissionServiceImpl extends ServiceImpl<PermissionMapper, PermissionDO> implements RolePermissionService {

    //  注入RolePermissionConverter用来转化PageDTO
    @Autowired
    RolePermissionConverter rolePermissionConverter;
    // 注入MyBatis-Plus的Mapper接口，用于数据库操作
    @Autowired
    private RolePermissionMapper rolePermissionMapper;  // 角色-权限关联表Mapper
    @Autowired
    private RoleMapper roleMapper;                      // 角色表Mapper
    @Autowired
    private PermissionMapper permissionMapper;            // 权限表Mapper

    @Autowired
    RolePermissionConverter permissionConverter;

    //  保存权限树(后台账号权限管理-权限管理)
    @Override
    public void savePermissions(PermissionCommand command) {
        // 将 PermissionCommand 转换为 PermissionDO
        PermissionDO permissionDO = permissionConverter.command2PermissionDO(command);

        // 顶级权限 parentPermission 设为 -1
        if (permissionDO.getParentPermission() == null) {
            permissionDO.setParentPermission(Long.valueOf("-1"));
        }

        // 插入主权限
        this.save(permissionDO);

        // 递归插入子权限
        if (command.getChildren() != null && !command.getChildren().isEmpty()) {
            for (PermissionCommand child : command.getChildren()) {
                // 设置子权限的父ID为当前插入的权限ID
                child.setParentPermission(String.valueOf(permissionDO.getId()));
                savePermissions(child);
            }
        }
    }

    // 获取权限树(后台账号权限管理-权限管理)
    @Override
    public List<PermissionDTO> getPermissions() {
        // 查询所有权限
        List<PermissionDO> allPermissions = this.list();

        // 用mapstruct批量转换
        List<PermissionDTO> allDTOs = permissionConverter.employeePermissionDO2DTO(allPermissions);

        // 构建id->DTO映射
        Map<String, PermissionDTO> idMap = new HashMap<>();
        for (PermissionDTO dto : allDTOs) {
            idMap.put(dto.getId(), dto);
            dto.setChildren(new ArrayList<>());
        }

        // 构建树结构
        List<PermissionDTO> roots = new ArrayList<>();
        for (PermissionDTO dto : allDTOs) {
            if ("-1".equals(dto.getParentPermission())) {
                roots.add(dto);
            } else {
                PermissionDTO parent = idMap.get(dto.getParentPermission());
                if (parent != null) {
                    parent.getChildren().add(dto);
                }
            }
        }
        return roots;
    }

    // 删除指定权限(后台账号权限管理-权限管理)
    @Override
    public DeletePermissionOperateDTO deletePermission(Long permissionId) {

        PermissionDO mainPermission = this.getById(permissionId);
        if (mainPermission == null) {
            return null; // 或抛出异常
        }

        // 1. 查询所有权限
        List<PermissionDO> allPermissions = this.list();

        // 2. 找到所有要删除的id（包括自己和所有子孙节点）
        Set<Long> toDelete = new HashSet<>();
        findAllChildren(permissionId, allPermissions, toDelete);

        // 3. 删除
        this.removeByIds(toDelete);

        // 4. 返回操作结果
        DeletePermissionOperateDTO dto = new DeletePermissionOperateDTO();
        dto.setId(mainPermission.getId());
        dto.setName(mainPermission.getName());
        dto.setPermissionType(mainPermission.getPermissionType() == null ? null : mainPermission.getPermissionType().toString());
        dto.setPermissionAlias(mainPermission.getPermissionAlias());
        return dto;
    }

    // 递归查找所有子节点
    private void findAllChildren(Long id, List<PermissionDO> all, Set<Long> result) {
        result.add(id);
        for (PermissionDO p : all) {
            if (p.getParentPermission() != null && id.equals(p.getParentPermission())) {
                findAllChildren(p.getId(), all, result);
            }
        }
    }

    // 更新权限树(后台账号权限管理-权限管理)
    @Override
    public void updatePermission(PermissionCommand command) {
        PermissionDO permissionDO = permissionConverter.command2PermissionDO(command);
        this.updateById(permissionDO);
        if (command.getChildren() != null && !command.getChildren().isEmpty()) {
            for (PermissionCommand child : command.getChildren()) {
                // 设置父ID
                child.setParentPermission(String.valueOf(permissionDO.getId()));
                updatePermission(child);
            }
        }

    }

    //    --------------------------------------------------------------------
    /*
        叶佳杰部分：
     */
    // 分页获取角色列表(后台账号权限管理-角色管理)
    @Override
    public PageDTO<RoleDTO> getRoleList(PageRequest pageRequest) {
        if (pageRequest.getKeyword() != null && pageRequest.getKeyword() != "") {
            //        1.利用通用service的方法操作数据库中的数据-根据pageRequest里面的查询关键字查询
            LambdaQueryWrapper<RoleDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(RoleDO::getName, pageRequest.getKeyword());
            //        2.查询出数据库中全部满足条件的人员数据
            List<RoleDO> roleDOS = roleMapper.selectList(lambdaQueryWrapper);
            //        3.计算查询出满足条件的个数
            long sum = roleDOS.size();
            //        4.利用mapstruct转化为PageDTO
            PageDTO<RoleDTO> pageDTO = rolePermissionConverter.roleList2Page(roleDOS, sum);
            return pageDTO;
        } else {
            Integer pageNum = pageRequest.getPageNum() != null ? pageRequest.getPageNum() : 1;
            Integer pageSize = pageRequest.getCount() != null ? pageRequest.getCount() : 10;
            QueryWrapper<RoleDO> queryWrapper = new QueryWrapper<>();
            queryWrapper = null;
            Page<RoleDO> page = new Page<>(pageNum, pageSize);
            Page<RoleDO> roleDOPage = roleMapper.selectPage(page, queryWrapper);
            List<RoleDO> records = roleDOPage.getRecords();
            int num = records.size();
            long numLong = num;
            PageDTO<RoleDTO> roleDTOPageDTO = rolePermissionConverter.roleList2Page(records, numLong);
            return roleDTOPageDTO;
        }
    }

    // 添加角色(后台账号权限管理-角色管理)
    @Override
    public void addRole(RoleCommand command) {
        if (command.getName() != null || command.getName() != "") {
            //            将前端传过来的数据转化为roledo，并自动隐射
            RoleDO roleDO = rolePermissionConverter.command2RoleDO(command);
            int insert = roleMapper.insert(roleDO);
            //            System.out.println("insert = " + insert);
        }
    }

    // 更新角色(后台账号权限管理-角色管理)
    @Override
    public void updateRole(RoleCommand roleCommand) {
        if (roleCommand.getName() != null || roleCommand.getName() != "") {
            //            将前端传过来的数据转化为roledo，并自动隐射
            RoleDO roleDO = rolePermissionConverter.command2RoleDO(roleCommand);
            int insert = roleMapper.updateById(roleDO);
            //            System.out.println("insert = " + insert);

        }

    }

    // 更新角色权限关系(后台账号权限管理-角色管理)
    @Override
    public void updateRolePermission(RolePermissionCommand command) {
        //        根据前端传过来的command，判断该角色是否被删除，以及该角色是否有权限
        //        获取前端传来的管理员角色id
        String roleId = command.getRoleId();
        //        获取前端传来的管理员角色权限id集合
        List<String> permissionsList = command.getPermissions();
        //        检查在授权的时候是否把所有权限都取消掉
        if (roleId == null || roleId == "" || permissionsList.isEmpty()) {
            throw new BusinessException("角色ID或权限集合不能为空", null);
        }
        //        查询数据库中该角色是否已被删除
        long roleIdLong = Long.parseLong(roleId);
        RoleDO roleDO = roleMapper.selectById(roleIdLong);
        if (roleDO == null || roleDO.getIsDeleted() == 1) {
            throw new BusinessException("角色不存在或已被删除", null);
        }

        //        查询角色已有的条件:RolePermission这张表，要用到permission_id
        QueryWrapper<RolePermissionDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId)
                .eq("is_deleted", 0);
        List<RolePermissionDO> rolePermissionDOS = rolePermissionMapper.selectList(queryWrapper);
        //        从查询出的RolePermission这张表中拿出permission_id
        Set<Long> existPermissionIds = rolePermissionDOS.stream().map(RolePermissionDO::getPermissionId).collect(Collectors.toSet());
        //        ------------------处理前端部分--------------------------
        //        将前端传来的id转化为long类型并且去重
        Set<Long> frontPermissionIds = permissionsList.stream().map(str -> {
            return Long.parseLong(str);
        }).collect(Collectors.toSet());
        //        利用filter过滤出数据库中没有添加的权限
        Set<Long> newPermissionIds = frontPermissionIds.stream().filter(id -> !existPermissionIds.contains(id)).collect(Collectors.toSet());
        //        如果没有新权限，则直接返回-原来的
        if (newPermissionIds.isEmpty()) {
            return;
        }
        //        删除权限，数据库中有但前端没有的权限-新加的
        Set<Long> toDeletePermissionIds = existPermissionIds.stream().filter(id -> !frontPermissionIds.contains(id)).collect(Collectors.toSet());
        //        处理新增权限-新加的
        if (!newPermissionIds.isEmpty()) {
            QueryWrapper<PermissionDO> permissionDOQueryWrapper = new QueryWrapper<>();
            permissionDOQueryWrapper.eq("is_deleted", 0) // 基础条件：权限未删除
                    .eq("permission_type", 2); // 假设需要校验权限类型为叶子节点（根据业务需求调整）

            // 仅当newPermissionIds非空时，添加IN条件
            if (!newPermissionIds.isEmpty()) {
                permissionDOQueryWrapper.in("id", newPermissionIds);
            }
            //            permissionDOQueryWrapper.in("id",toDeletePermissionIds)
            //                    .eq("is_deleted",0);
            List<PermissionDO> validPermissions = permissionMapper.selectList(permissionDOQueryWrapper);
            //            提取有效权限id
            Set<Long> validAddPermissionIds = validPermissions.stream().map(PermissionDO::getId).collect(Collectors.toSet());
            //            检查是否存在无效权限
            HashSet<Long> invalidAddPermissionIds = new HashSet<>(newPermissionIds);
            invalidAddPermissionIds.removeAll(validAddPermissionIds);
            //        插入
            List<RolePermissionDO> addList = validAddPermissionIds.stream().map(permId -> {
                RolePermissionDO rolePermissionDO = new RolePermissionDO();
                rolePermissionDO.setRoleId(roleIdLong);
                rolePermissionDO.setPermissionId(permId);
                rolePermissionDO.setIsDeleted(0);
                return rolePermissionDO;
            }).collect(Collectors.toList());
            List<BatchResult> insert = rolePermissionMapper.insert(addList);
            System.out.println("insert = " + insert);

        }
        //        处理删除权限-新加的
        if (!toDeletePermissionIds.isEmpty()) {
            UpdateWrapper<RolePermissionDO> deleteWrapper = new UpdateWrapper<>();
            deleteWrapper.eq("role_id", roleId)
                    .in("permission_id", toDeletePermissionIds)
                    .set("is_deleted", 1)
                    .set("updated_time", LocalDateTime.now());
            rolePermissionMapper.update(null, deleteWrapper);
        }
        ////        如果没有新权限，则直接返回-原来的
        //        if (newPermissionIds.isEmpty()) {
        //            return;
        //        }
        ////        检查新增权限是否是叶子节点
        //        QueryWrapper<PermissionDO> permissionDOQueryWrapper = new QueryWrapper<>();
        //        permissionDOQueryWrapper.in("id", newPermissionIds)
        //                .eq("permission_type", 2)
        //                .eq("is_deleted", 0);
        //        List<PermissionDO> permissionDOS = permissionMapper.selectList(permissionDOQueryWrapper);
        ////        将permission表中的permission_id提取出来
        //        Set<Long> permissionDOIds = permissionDOS.stream().map(PermissionDO::getId).collect(Collectors.toSet());
        ////        插入
        //        List<RolePermissionDO> newRolPermissionDO = newPermissionIds.stream().map(permId -> {
        //            RolePermissionDO rolePermissionDO = new RolePermissionDO();
        //            rolePermissionDO.setRoleId(roleIdLong);
        //            rolePermissionDO.setPermissionId(permId);
        //            rolePermissionDO.setIsDeleted(0);
        //            return rolePermissionDO;
        //        }).collect(Collectors.toList());
        //        List<BatchResult> insert = rolePermissionMapper.insert(newRolPermissionDO);
        //        System.out.println("insert = " + insert);

    }

    // 获取角色权限树(后台账号权限管理-角色管理点击授权时返回的角色授权树)
    @Override
    public RolePermissionDTO getRolePermissionList(Long roleId) {
        //        检查角色信息是否存在
        RoleDO roleDO = roleMapper.selectById(roleId);
        if (roleDO == null || roleDO.getIsDeleted() == 1) {
            throw new BusinessException("角色被删除不存在了", null);
        }
        //        查询出数据库中所有的有效权限,也就是没有被删除的权限（包括1级和2级的）
        QueryWrapper<PermissionDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", 0);
        List<PermissionDO> allPermissionDOS = permissionMapper.selectList(queryWrapper);
        //        从数据库中查询到的所有有效权限里，拆封出根级的目录-新加部分
        List<PermissionDO> topPermissions = allPermissionDOS.stream().filter(perm -> perm.getParentPermission() != null && perm.getParentPermission() == -1).collect(Collectors.toList());
        List<PermissionDTO> topPermissionsDTO = rolePermissionConverter.employeePermissionDO2DTO(topPermissions);

        //        从数据库中查询到的所有有效权限里，拆封出1级的目录
        List<PermissionDO> pagePermissionsOne = allPermissionDOS.stream().filter(perm -> perm.getPermissionType() == 1).collect(Collectors.toList());
        List<PermissionDTO> pagePermissionsDTOOne = rolePermissionConverter.employeePermissionDO2DTO(pagePermissionsOne);

        //        从数据库中查询到的所有有效权限里，拆封出2级的目录
        List<PermissionDO> accessPermissionsTwo = allPermissionDOS.stream().filter(perm -> perm.getPermissionType() == 2).collect(Collectors.toList());
        List<PermissionDTO> accessPermissionsDTOTwo = rolePermissionConverter.employeePermissionDO2DTO(accessPermissionsTwo);

        //        将拆封出的根级的目录的DTO放入到map里,把根级目录的id作为键-新加部分
        HashMap<Long, PermissionDTO> topPermissionMap = new HashMap<>();
        for (PermissionDTO permissionDTO : topPermissionsDTO) {
            topPermissionMap.put(Long.parseLong(permissionDTO.getId()), permissionDTO);
        }

        //        将拆封出1级的目录的DTO放入到map里,把1级目录的id作为键
        HashMap<Long, PermissionDTO> pagePermissionsMap = new HashMap<>();
        for (PermissionDTO permissionDTO : pagePermissionsDTOOne) {
            //            获取1级目录的父亲id-新加部分
            Long parentPermissionID = Long.parseLong(permissionDTO.getParentPermission());
            //            检查1级目录是否有父节点-新加部分
            if (topPermissionMap.containsKey(parentPermissionID)) {
                topPermissionMap.get(parentPermissionID).getChildren().add(permissionDTO);
            }

            pagePermissionsMap.put(Long.parseLong(permissionDTO.getId()), permissionDTO);
        }
        //        将拆封出来的2级目录绑定到1级目录里-同时先检验一下这个2级目录和1级目录有绑定关系没
        for (PermissionDTO accessPermDTOTwo : accessPermissionsDTOTwo) {
            Long parentId = Long.parseLong(accessPermDTOTwo.getParentPermission());
            if (parentId == null) {
                continue;
            }
            //            插入1级里
            pagePermissionsMap.get(parentId).getChildren().add(accessPermDTOTwo);
        }
        //        转化为list
        //        List<PermissionDTO> sysPermissions = pagePermissionsMap.values().stream().filter(permDTO -> !permDTO.getChildren().isEmpty()).collect(Collectors.toList());
        List<PermissionDTO> sysPermissions = topPermissionMap.values().stream().filter(permDTO -> !permDTO.getChildren().isEmpty()).collect(Collectors.toList());
        //        接下来需要更具roleid查询到管理员已经绑定的权限
        QueryWrapper<RolePermissionDO> rolePermissionDOQueryWrapper = new QueryWrapper<>();
        rolePermissionDOQueryWrapper.eq("role_id", roleId)
                .eq("is_deleted", 0);
        List<RolePermissionDO> rolePermissionDOS = rolePermissionMapper.selectList(rolePermissionDOQueryWrapper);
        //        从查询到管理员的所有列表里抽取出已绑定的权限的id
        List<String> assignedPermissionID = rolePermissionDOS.stream().map(rp -> String.valueOf(rp.getPermissionId())).collect(Collectors.toList());
        //        封装到rolepermissiondto中
        RolePermissionDTO rolePermissionDTO = new RolePermissionDTO();
        rolePermissionDTO.setSystemPermissions(sysPermissions);
        rolePermissionDTO.setAssignedPermissions(assignedPermissionID);
        return rolePermissionDTO;
    }

    // 删除角色(后台账号权限管理-角色管理)
    @Override
    public DeleteRoleOperateDTO deleteRole(Long roleId) {
        //        先根据id去数据库查询有没有这个管理员
        RoleDO roleDO = roleMapper.selectById(roleId);
        if (roleDO == null || roleDO.getIsDeleted() == 1) {
            throw new BusinessException("角色被删除不存在了", null);
        }
        //        先根据roleid删除关系
        QueryWrapper<RolePermissionDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId)
                .eq("is_deleted", 0);
        //        检查一下rolepermission表中有没有绑定关系
        List<RolePermissionDO> rolePermissionDOS = rolePermissionMapper.selectList(queryWrapper);
        if (rolePermissionDOS != null && !rolePermissionDOS.isEmpty()) {
            //        更具roleid删除关系
            rolePermissionMapper.delete(queryWrapper);
        }
        //        根据roleid删除role表中的角色
        roleMapper.deleteById(roleId);
        //        记录日志
        DeleteRoleOperateDTO deleteRoleOperateDTO = rolePermissionConverter.toDeleteRoleOperateDTO(roleDO);
        return deleteRoleOperateDTO;
    }

    // 删除角色(后台账号权限管理-角色管理)
    @Override
    public DeleteRolePermissionOperateDTO deleteRolePermission(Long roleId, List<Long> permissionId) {
        //        根据roleid从permission数据库里查询出所有的权限
        QueryWrapper<RolePermissionDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId)
                .eq("is_deleted", 0);
        List<RolePermissionDO> rolePermissionDOS = rolePermissionMapper.selectList(queryWrapper);
        if (rolePermissionDOS == null && !rolePermissionDOS.isEmpty()) {
            throw new BusinessException("角色被删除不存在了", null);
        }
        //        接下来要和前端传过来的permissionId做比对，找出数据库里多出来的删掉
        //        先提取出来List<RolePermissionDO>里面的permissionId
        Set<Long> rolePermissionidDOS = rolePermissionDOS.stream().map(RolePermissionDO::getPermissionId).collect(Collectors.toSet());
        //        处理穿过来permissionid为空的情况
        Set<Long> targetPermissionIds = permissionId == null ? new HashSet<>() : new HashSet<>(permissionId);
        //        计算出来数据库里比传过来集合多的
        List<Long> deletPermissionIDS = rolePermissionidDOS.stream().filter(id -> !targetPermissionIds.contains(id)).collect(Collectors.toList());
        //        直接在rolepermission表里删除这些权限
        for (Long deletRolePermissionID : deletPermissionIDS) {
            QueryWrapper<RolePermissionDO> rolePermissionDOQueryWrapper = new QueryWrapper<>();
            rolePermissionDOQueryWrapper.eq("permission_id", deletRolePermissionID);
            rolePermissionMapper.delete(rolePermissionDOQueryWrapper);
        }
        //        记录日志部分
        //        权限别名日志
        QueryWrapper<PermissionDO> queryWrapperLog = new QueryWrapper<>();
        queryWrapperLog.eq("id", deletPermissionIDS);
        List<PermissionDO> rolePermissionsLog = permissionMapper.selectList(queryWrapperLog);
        DeleteRolePermissionOperateDTO deleteRolePermissionOperateDTO = new DeleteRolePermissionOperateDTO();
        String permissionAliasLog = "";
        for (PermissionDO permissionDO : rolePermissionsLog) {
            permissionAliasLog = permissionAliasLog + permissionDO.getPermissionAlias();
        }
        deleteRolePermissionOperateDTO.setPermissionAlias(permissionAliasLog);
        return deleteRolePermissionOperateDTO;
    }
}
